package com.wenx.v3system.modular.platform.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.wenx.v3core.response.R;
import com.wenx.v3secure.annotation.RequiresPermissions;
import com.wenx.v3secure.enums.PlatformPermission;
import com.wenx.v3system.modular.platform.domain.dto.PlatformRoleMenuDto;
import com.wenx.v3system.modular.platform.domain.query.PlatformRoleQuery;
import com.wenx.v3system.modular.platform.service.PlatformPermissionService;
import com.wenx.v3system.modular.platform.service.PlatformRoleMenuService;
import com.wenx.v3system.modular.platform.service.PlatformUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import jakarta.validation.Valid;
import java.util.List;

import static com.wenx.v3secure.annotation.RequiresPermissions.Logical.OR;

/**
 * 平台权限管理控制器
 *
 * @author wenx
 */
@Slf4j
@RestController
@RequestMapping("/api/v3/platform/permissions")
@Tag(name = "平台权限管理", description = "平台权限相关接口")
@RequiredArgsConstructor
@Validated
public class PlatformPermissionController {

    private final PlatformUserService platformUserService;
    private final PlatformRoleMenuService platformRoleMenuService;
    private final PlatformPermissionService platformPermissionService;

    /**
     * 分页查询角色及其菜单权限
     */
    @PostMapping("/roles/page")
    @Operation(summary = "分页查询角色权限", description = "分页查询角色列表并包含每个角色的菜单权限信息")
    @RequiresPermissions(value = {PlatformPermission.PLATFORM_ALL_CODE, PlatformPermission.PLATFORM_ROLE_READ_CODE}, logical = OR)
    public R getRolesWithMenusPage(@RequestBody @Valid PlatformRoleQuery query) {
        IPage<?> rolesPage = platformPermissionService.getRolesWithMenusPage(query);
        return R.ok(rolesPage);
    }

    /**
     * 获取权限码列表
     */
    @GetMapping("/codes")
    @Operation(summary = "获取权限码列表", description = "获取所有权限的编码列表")
    @RequiresPermissions(value = {PlatformPermission.PLATFORM_ALL_CODE, PlatformPermission.PLATFORM_ROLE_READ_CODE}, logical = OR)
    public R getPermissionCodes() {
        List<String> permissionCodes = platformPermissionService.getAllPermissionCodes();
        return R.ok(permissionCodes);
    }

    /**
     * 根据用户获取权限
     */
    @GetMapping("/by-user/{userId}")
    @Operation(summary = "根据用户获取权限", description = "获取指定用户的权限列表")
    @RequiresPermissions(value = {PlatformPermission.PLATFORM_ALL_CODE, PlatformPermission.PLATFORM_ROLE_READ_CODE}, logical = OR)
    public R getPermissionsByUser(@PathVariable Long userId) {
        List<String> permissions = platformUserService.getUserPermissions(userId);
        return R.ok(permissions);
    }

    /**
     * 根据角色编码获取菜单列表
     */
    @GetMapping("/role/{roleCode}/menus")
    @Operation(summary = "获取角色菜单", description = "根据角色编码获取该角色拥有的菜单列表")
    @RequiresPermissions(value = {PlatformPermission.PLATFORM_ALL_CODE, PlatformPermission.PLATFORM_ROLE_READ_CODE}, logical = OR)
    public R getRoleMenus(@PathVariable String roleCode) {

        log.debug("获取角色菜单: roleCode={}", roleCode);
        List<PlatformRoleMenuDto> menus = platformRoleMenuService.getMenusByRoleCode(roleCode);
        return R.ok(menus);
    }

    /**
     * 根据角色编码获取菜单编码列表
     */
    @GetMapping("/role/{roleCode}/menu-codes")
    @Operation(summary = "获取角色菜单编码", description = "根据角色编码获取该角色拥有的菜单编码列表")
    @RequiresPermissions(value = {PlatformPermission.PLATFORM_ALL_CODE, PlatformPermission.PLATFORM_ROLE_READ_CODE}, logical = OR)
    public R getRoleMenuCodes(@PathVariable String roleCode) {

        log.debug("获取角色菜单编码: roleCode={}", roleCode);
        List<String> menuCodes = platformRoleMenuService.getMenuCodesByRoleCode(roleCode);
        return R.ok(menuCodes);
    }

    /**
     * 为角色分配菜单
     */
    @PostMapping("/role/{roleCode}/assign-menus")
    @Operation(summary = "分配角色菜单", description = "为指定角色分配菜单权限")
    @RequiresPermissions(value = {PlatformPermission.PLATFORM_ALL_CODE, PlatformPermission.PLATFORM_ROLE_ALL_CODE}, logical = OR)
    public R assignMenusToRole(
            @PathVariable String roleCode,
            @RequestBody List<String> menuCodes) {

        log.info("为角色分配菜单: roleCode={}, menuCodes={}", roleCode, menuCodes);
        platformRoleMenuService.assignMenusToRole(roleCode, menuCodes);
        return R.ok("角色菜单分配成功");
    }

    /**
     * 根据菜单编码获取拥有该菜单的角色列表
     */
    @GetMapping("/menu/{menuCode}/roles")
    @Operation(summary = "获取菜单角色", description = "根据菜单编码获取拥有该菜单的角色编码列表")
    @RequiresPermissions(value = {PlatformPermission.PLATFORM_ALL_CODE, PlatformPermission.PLATFORM_ROLE_READ_CODE}, logical = OR)
    public R getMenuRoles(@PathVariable String menuCode) {

        log.debug("获取菜单角色: menuCode={}", menuCode);
        List<String> roleCodes = platformRoleMenuService.getRoleCodesByMenuCode(menuCode);
        return R.ok(roleCodes);
    }

    /**
     * 检查角色是否拥有指定菜单
     */
    @GetMapping("/role-menu/check")
    @Operation(summary = "检查角色菜单权限", description = "检查指定角色是否拥有指定菜单权限")
    @RequiresPermissions(value = {PlatformPermission.PLATFORM_ALL_CODE, PlatformPermission.PLATFORM_ROLE_READ_CODE}, logical = OR)
    public R hasMenu(
            @Parameter(description = "角色编码", required = true) String roleCode,
            @Parameter(description = "菜单编码", required = true) String menuCode) {

        log.debug("检查角色菜单权限: roleCode={}, menuCode={}", roleCode, menuCode);
        boolean hasMenu = platformRoleMenuService.hasMenu(roleCode, menuCode);
        return R.ok(hasMenu);
    }

    /**
     * 删除角色的所有菜单关联
     */
    @DeleteMapping("/role/{roleCode}/menus")
    @Operation(summary = "删除角色菜单", description = "删除指定角色的所有菜单关联")
    @RequiresPermissions(value = {PlatformPermission.PLATFORM_ALL_CODE, PlatformPermission.PLATFORM_ROLE_ALL_CODE}, logical = OR)
    public R removeRoleMenus(@PathVariable String roleCode) {

        log.info("删除角色菜单: roleCode={}", roleCode);
        platformRoleMenuService.removeAllMenusByRoleCode(roleCode);
        return R.ok("角色菜单删除成功");
    }

    /**
     * 删除菜单的所有角色关联
     */
    @DeleteMapping("/menu/{menuCode}/roles")
    @Operation(summary = "删除菜单角色", description = "删除指定菜单的所有角色关联")
    @RequiresPermissions(value = {PlatformPermission.PLATFORM_ALL_CODE, PlatformPermission.PLATFORM_ROLE_ALL_CODE}, logical = OR)
    public R removeMenuRoles(@PathVariable String menuCode) {

        log.info("删除菜单角色: menuCode={}", menuCode);
        platformRoleMenuService.removeAllRolesByMenuCode(menuCode);
        return R.ok("菜单角色删除成功");
    }

}